package com.plian.system.service.szyd.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.bean.wtzg.RectificationSituationExcelBean;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.dao.bt.baseinfo.BaseInfoDao;
import com.plian.system.entity.ms.RectificationSituation;
import com.plian.system.entity.szyd.TbImportantMatters;
import com.plian.system.excel.ImportResult;
import com.plian.system.mapper.szyd.TbImportantMattersMapper;
import com.plian.system.model.ObjResult;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.search.TokenSearch;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.mybatis.support.Query;
import com.plian.system.service.ms.check.RectificationExcelCheckData;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.file.FileService;
import com.plian.system.service.sys.orgzation.OrgzationService;
import com.plian.system.service.szyd.ITbImportantMattersService;
import com.plian.system.service.szyd.check.TbImportantMattersExcelBean;
import com.plian.system.service.szyd.check.TbImportantMattersExcelCheckData;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.szyd.TbImportantMattersVO;
import com.plian.system.wrapper.szyd.TbImportantMattersWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Future;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * 三重一大-重要事项 服务实现类
 *
 * @author zhangsk
 */
@Slf4j
@Service
@AllArgsConstructor
public class TbImportantMattersServiceImpl extends BaseServiceImpl<TbImportantMattersMapper, TbImportantMatters> implements ITbImportantMattersService, BaseFlowService {

	private FormWorkflowService formWorkflowService;

	private IFormCodeService formCodeService;

	private FileService fileService;

	private TbImportantMattersWrapper tbImportantMattersWrapper;
	// 字典map
	private static HashMap<String, List<String>> codeMap = new HashMap<>();
	//名称转cod 用参照字典（参照key,<name,id>）(需确保每个名字唯一)
	private static HashMap<String, Map<String, String>> nameMap = new HashMap<>();
	@Autowired
	BaseInfoDao baseInfoDao;
	private Environment environment;
	private OrgzationService orgzationService;
	private static Map<String, String> fileNameMap = new HashMap<>();
	@Override
	public HashMap<String,Object> commit(String id) {
		handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);
		//将需要提交的流程变量返回，用于工作流侧
		return new HashMap<String,Object>();
	}

	@Override
	public Boolean finish(String id) {
		return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
	}

	@Override
	public Boolean reject(String id, int formState, String comment) {
		return handleStatus(Long.valueOf(id), formState);
	}

	@Override
	public Boolean checkIsExisted(Long id, String code) {
		if (Optional.ofNullable(code).isPresent()) {
			TbImportantMatters tbImportantMatters = new TbImportantMatters();
//			tbImportantMatters.setCode(code);
			if (Optional.ofNullable(getOne(Condition.getQueryWrapper(tbImportantMatters))).isPresent()) {
				if (id == null || !id.equals(getOne(Condition.getQueryWrapper(tbImportantMatters)).getId())) {
					return false;
				}
			}
		}
		return true;
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public Boolean submit(TbImportantMatters tbImportantMatters) {

		boolean result = saveOrUpdate(tbImportantMatters);
		return result;
	}

	@Override
	public Boolean checkCancel(Long id) {
		TbImportantMatters tbImportantMatters = getById(id);
		if (!Optional.ofNullable(tbImportantMatters).isPresent()) {
			return false;
		}
		return true;
	}

	@Override
	public boolean saveOrUpdate(TbImportantMatters tbImportantMatters) {
		if (!Optional.ofNullable(tbImportantMatters.getStatus()).isPresent()) {
			tbImportantMatters.setStatus(UNREVIEWED);
		}

		if (!Optional.ofNullable(tbImportantMatters.getId()).isPresent()) {
			//根据单据类型生成单据编码
			if("195001".equals(tbImportantMatters.getMatterType())){
				tbImportantMatters.setCode(formCodeService.getCode(FormTypeConstant.IMPORTANT_MATTERS_ZDJC));
				tbImportantMatters.setFormType(String.valueOf(FormTypeConstant.IMPORTANT_MATTERS_ZDJC));
			}else if("195002".equals(tbImportantMatters.getMatterType())){
				tbImportantMatters.setCode(formCodeService.getCode(FormTypeConstant.IMPORTANT_MATTERS_RSRM));
				tbImportantMatters.setFormType(String.valueOf(FormTypeConstant.IMPORTANT_MATTERS_RSRM));
			}else if("195003".equals(tbImportantMatters.getMatterType())){
				tbImportantMatters.setCode(formCodeService.getCode(FormTypeConstant.IMPORTANT_MATTERS_ZDAP));
				tbImportantMatters.setFormType(String.valueOf(FormTypeConstant.IMPORTANT_MATTERS_ZDAP));
			}else if("195004".equals(tbImportantMatters.getMatterType())){
				tbImportantMatters.setCode(formCodeService.getCode(FormTypeConstant.IMPORTANT_MATTERS_DEZJ));
				tbImportantMatters.setFormType(String.valueOf(FormTypeConstant.IMPORTANT_MATTERS_DEZJ));
			}
		}
		boolean result = super.saveOrUpdate(tbImportantMatters);
		if (result){
			fileService.edit(String.valueOf(tbImportantMatters.getId()), tbImportantMatters.getDocList());
//			fileService.saveAll(String.valueOf(tbImportantMatters.getId()), tbImportantMatters.getDocList());
		}
//		else {
//			fileService.edit(String.valueOf(tbImportantMatters.getId()), tbImportantMatters.getDocList());
//		}
		return result;
	}


	/**
	 * 统一处理状态机事件方法
	 *
	 * @param id          主键
	 * @param updateStatus 更新状态
	 * @return boolean
	 */
	private Boolean handleStatus(Long id, int updateStatus) {
		try {
			TbImportantMatters tbImportantMatters = getById(id);
			/**
			 * 设置审批人和审批时间
			 */
			if (updateStatus == FormStatusConstant.FINISH){
				tbImportantMatters.setApprovedUser(TokenUtil.getTokenUserId());
				Date now = DateUtil.now();
				tbImportantMatters.setApprovedTime(now);
			}
			tbImportantMatters.setStatus(updateStatus);
			updateById(tbImportantMatters);
			return true;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
			return false;
		}
	}

	@Override
	public List<PageData> findByIds(List<String> formIds) {
		LambdaQueryWrapper<TbImportantMatters> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.in(TbImportantMatters::getId, Func.toLongList(org.apache.commons.lang3.StringUtils.join(formIds, StringPool.COMMA)));
		List<TbImportantMatters> tbImportantMatters = list(queryWrapper);
		List<TbImportantMattersVO> tbImportantMattersVOS = tbImportantMattersWrapper.entityToVO(tbImportantMatters);
		List<PageData> pageDataList = new ArrayList<>();
		try{
			if (CollectionUtil.isNotEmpty(tbImportantMattersVOS)){
				for (TbImportantMattersVO vo : tbImportantMattersVOS){
					PageData pd = new PageData();
					pd.put("id", vo.getId());
					pd.put("UNITNAME", vo.getFillCompanyName());
					pd.put("APPLICANTNAME", vo.getCreateUserName());
					pd.put("applicantId", vo.getCreateUser());
					pd.put("applyOrganizationId", vo.getCreateCompanyId());
					if("195001".equals(vo.getMatterType())){
						pd.put("formType", FormTypeConstant.IMPORTANT_MATTERS_ZDJC);
					}else if("195002".equals(vo.getMatterType())){
						pd.put("formType", FormTypeConstant.IMPORTANT_MATTERS_RSRM);
					}else if("195003".equals(vo.getMatterType())){
						pd.put("formType", FormTypeConstant.IMPORTANT_MATTERS_ZDAP);
					}else if("195004".equals(vo.getMatterType())){
						pd.put("formType", FormTypeConstant.IMPORTANT_MATTERS_DEZJ);
					}
					pd.put("orgName", vo.getFillCompanyName());
					pageDataList.add(pd);
				}
			}
			return pageDataList;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		return pageDataList;
	}

	@Override
	public List<Integer> getFormType() {
		return Arrays.asList(FormTypeConstant.IMPORTANT_MATTERS_ZDJC,
				FormTypeConstant.IMPORTANT_MATTERS_ZDAP,
				FormTypeConstant.IMPORTANT_MATTERS_RSRM,
				FormTypeConstant.IMPORTANT_MATTERS_DEZJ);
	}

	@Override
	public void goBackToStash(String formId) {
		handleStatus(Long.valueOf(formId), UNREVIEWED);
	}


	@Override
	@Async("ttlExecutor")
	public Future<ImportResult> importExcel(String progressId, InputStream inputStream) {
		String progress = "progress";
		Date now = DateUtil.now();
		String key = progressId + "#half:hour";
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		//在所有校验前统一初始化所有字典
		initMap();

		try {
			byte[] bytes = IOUtils.toByteArray(inputStream);
			inputStream = new ByteArrayInputStream(bytes);
			List<Object> baseList = new ArrayList<>();
			EasyExcel.read(inputStream).build()
					.read(EasyExcel.readSheet(0).headRowNumber(2).head(TbImportantMattersExcelBean.class)
							.registerReadListener(new PageReadListener<>(list -> baseList.addAll(list))).build());
			int size = baseList.size();
			ImportResult importResult = TbImportantMattersExcelCheckData.checkStaffData(baseList, key, codeMap, nameMap);
			if (!importResult.isSuccess()) {
				CacheUtil.put(progress, progress, key, importResult.getMsg());
				return new AsyncResult<>(importResult);
			}
			if(baseList!=null&&baseList.size()>0){
				int count = 0;

				for (Object obj: baseList) {
					TbImportantMattersExcelBean tbImportantMattersExcelBean=(TbImportantMattersExcelBean)obj;
					TbImportantMatters tbImportantMatters=new TbImportantMatters();
					BeanUtils.copyProperties(tbImportantMattersExcelBean,tbImportantMatters);

					SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy.MM.dd");
					Date decisionDate = sdf1.parse(tbImportantMattersExcelBean.getDecisionDateStr());
					Date decisionMeetDate = sdf1.parse(tbImportantMattersExcelBean.getDecisionMeetDateStr());
					tbImportantMatters.setDecisionDate(decisionDate);
					tbImportantMatters.setDecisionMeetDate(decisionMeetDate);
					List<PageData> pageDataList=baseInfoDao.findbyParentid("194");
					if(pageDataList!=null&&pageDataList.size()>0){
						for (PageData pageData: pageDataList) {
							String code=pageData.getString("code");
							String name=pageData.getString("name");
							if(StringUtil.isNotBlank(name)&&StringUtil.isNotBlank(code)){
								if(name.equals(tbImportantMattersExcelBean.getDecisionMeetType())){
									tbImportantMatters.setDecisionMeetType(code);
								}
							}
						}
					}
					List<PageData> pageDataList1=baseInfoDao.findbyParentid("195");
					if(pageDataList1!=null&&pageDataList1.size()>0){
						for (PageData pageData: pageDataList1) {
							String code=pageData.getString("code");
							String name=pageData.getString("name");
							if(StringUtil.isNotBlank(name)&&StringUtil.isNotBlank(code)){
								if(name.equals(tbImportantMattersExcelBean.getMatterType())){
									tbImportantMatters.setMatterType(code);
								}
							}
						}
					}
					if(tbImportantMattersExcelBean.getIsFrontStr().equals("是")){
						tbImportantMatters.setIsFront(1);
					}else{
						tbImportantMatters.setIsFront(0);
					}
					tbImportantMatters.setFillCompanyId(TokenUtil.getTokenOrgId());
					tbImportantMatters.setFillDate(sdf.format(new Date()));
					tbImportantMatters.setCreateCompanyId(TokenUtil.getTokenOrgId());
					tbImportantMatters.setCreateTime(new Date());
					tbImportantMatters.setCreateUser(TokenUtil.getTokenUserId());
					tbImportantMatters.setUpdateTime(new Date());
					tbImportantMatters.setIsDeleted(0);
					this.saveOrUpdate(tbImportantMatters);
					count++;
					int value = count * 100 / size;
					CacheUtil.put(progress, progress, key, value + 100);
				}

			}
		}catch (Exception e) {
			e.printStackTrace();
			log.error("导入失败");
			CacheUtil.put(progress, progress, key,"导入失败");
			return new AsyncResult<>(new ImportResult(false,"导入失败"));
		}
		CacheUtil.put(progress, progress, key,"导入成功");
		return new AsyncResult<>(new ImportResult(true,"导入成功"));
	}

	private void initMap() {
		//注：以下key值与实际配置的参照无关联，仅为了方便理解使用了相同名称
		//完成情况


		try {
			List<PageData> pageDataList=baseInfoDao.findbyParentid("194");
			List<String> a=new ArrayList<>();
			for (PageData pageData: pageDataList) {
				String name=pageData.getString("name");
				a.add(name);
			}
			codeMap.put("decisionMeetTypeRef", a);
			List<PageData> pageDataListTwo=baseInfoDao.findbyParentid("195");
			List<String> b=new ArrayList<>();
			for (PageData pageData: pageDataListTwo) {
				String name=pageData.getString("name");
				b.add(name);
			}
			codeMap.put("matterTypeRef", b);
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
	}
	@Override
	public String export(String matterType){
		String key = System.currentTimeMillis() + StringPool.DASH + UUID.randomUUID().toString().replace(StringPool.DASH, "");
		String fileName = key + ".xlsx";
		String exportPath = environment.getProperty("excel.path");

		/**
		 * 导出路径不存在则创建
		 */
		File file = new File(exportPath);
		if (!file.exists()) {
			file.mkdirs();
		}
		InputStream inputStream = this.getClass().getResourceAsStream("/exceldemo/TbImportantMattersExport.xlsx");
		ExcelWriter excelWriter = EasyExcel.write(exportPath + fileName).withTemplate(inputStream).build();

		// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
		// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
		// 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存

		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
		// 表二
		WriteSheet staffFilesWriteSheet = EasyExcel.writerSheet(0).build();
		QueryWrapper<TbImportantMatters> queryWrapper = SearchParamEntiy.getQueryWrapper(
				Condition.getQueryWrapper(new TbImportantMatters()), new ArrayList<>()
		);
		TokenSearch<TbImportantMatters> tokenSearch = new TokenSearch<>();
		tokenSearch.addTokenNoFlowQuery(queryWrapper, new Query().setFlag(0));
		if(StringUtil.isNotBlank(matterType)){
			queryWrapper.eq("matter_type",matterType);
		}
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat sdf1=new SimpleDateFormat("yyyy.MM.dd");
		List<TbImportantMatters> tbImportantMattersList=this.list(queryWrapper);
		List<TbImportantMattersExcelBean> tbImportantMattersExcelBeanList=new ArrayList<>();
		if(tbImportantMattersList!=null&&tbImportantMattersList.size()>0){
			Integer count =0;
			for (TbImportantMatters tbImportantMatters: tbImportantMattersList) {
				if(tbImportantMatters!=null){
					TbImportantMattersExcelBean tbImportantMattersExcelBean=new TbImportantMattersExcelBean();
					BeanUtils.copyProperties(tbImportantMatters,tbImportantMattersExcelBean);
					if(tbImportantMatters.getDecisionDate()!=null){
						tbImportantMattersExcelBean.setDecisionDateStr(sdf1.format(tbImportantMatters.getDecisionDate()));
					}
					if(tbImportantMatters.getDecisionMeetDate()!=null){
						tbImportantMattersExcelBean.setDecisionMeetDateStr(sdf1.format(tbImportantMatters.getDecisionMeetDate()));
					}
					if(tbImportantMatters.getIsFront()!=null){
						if(tbImportantMatters.getIsFront()==1){
							tbImportantMattersExcelBean.setIsFrontStr("是");
						}
						if(tbImportantMatters.getIsFront()==0){
							tbImportantMattersExcelBean.setIsFrontStr("否");
						}
					}

					try {
						List<PageData> pageDataList = baseInfoDao.findbyParentid("194");
						if (pageDataList != null && pageDataList.size() > 0) {
							for (PageData pageData : pageDataList) {
								String code = pageData.getString("code");
								String name = pageData.getString("name");
								if (StringUtil.isNotBlank(name) && StringUtil.isNotBlank(code)) {
									if (code.equals(tbImportantMatters.getDecisionMeetType())) {
										tbImportantMattersExcelBean.setDecisionMeetType(name);
									}
								}
							}
						}
						List<PageData> pageDataList1 = baseInfoDao.findbyParentid("195");
						if (pageDataList1 != null && pageDataList1.size() > 0) {
							for (PageData pageData : pageDataList1) {
								String code = pageData.getString("code");
								String name = pageData.getString("name");
								if (StringUtil.isNotBlank(name) && StringUtil.isNotBlank(code)) {
									if (code.equals(tbImportantMatters.getMatterType())) {
										tbImportantMattersExcelBean.setMatterType(name);
									}
								}
							}
						}
					}catch (Exception e){
						e.getStackTrace();
					}
					count=count+1;
					tbImportantMattersExcelBean.setSerialNumber(String.valueOf(count));
					tbImportantMattersExcelBeanList.add(tbImportantMattersExcelBean);
				}
			}
		}
		excelWriter.fill(tbImportantMattersExcelBeanList, fillConfig, staffFilesWriteSheet);
		excelWriter.finish();
		PageData org = orgzationService.getCompanyNameById(TokenUtil.getTokenOrgId());
		String companyName = "";
		if (org != null) {
			companyName = org.getString("name");
		}
		String excelName = companyName + "_三重一大";
		fileNameMap.put(key, excelName);
		return key;
	}
	@Override
	public void download(String key, HttpServletResponse response) {
		if (!fileNameMap.containsKey(key)) {
			log.error("BaseInvestmentPlanServiceImpl 导出excel失败--------> key " + key);
			return;
		}
		String excelName = fileNameMap.get(key);
		String excelPath = environment.getProperty("excel.path") + "/" + key + ".xlsx";
		FileTools.exportExcel(excelPath, excelName, response);
		fileNameMap.remove(key);
	}
}
